package com.elcom.roaming.common.server;

import java.util.StringTokenizer;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.slf4j.Logger;

import com.elcom.ipc_as_smpp.ipcserver.level1.MessageListener;
import com.elcom.ipc_as_smpp.pdu.IPCData;
import com.elcom.roaming.module.collection.match.UIMatchingObjects;
import com.elcom.roaming.module.collection.match.UIMessage;
import com.elcom.roaming.module.synthesis.isup.ISUPMatchingObjects;
import com.elcom.roaming.module.synthesis.isup.ISUPMessage;
import com.elcom.roaming.module.synthesis.pr.PRMatchingObjects;
import com.elcom.roaming.module.synthesis.pr.PRMessage;

public class SMPPMessageListener implements MessageListener{

	private Logger logger;
	private UIMatchingObjects uiMatching;
	private ISUPMatchingObjects isupMatching;
	private PRMatchingObjects prMatching;
	
	public SMPPMessageListener(Logger logger, UIMatchingObjects matching) {
		this.logger = logger;
		this.uiMatching = matching;
	}

	public SMPPMessageListener(Logger logger, ISUPMatchingObjects isupMatching, PRMatchingObjects prMatching) {
		this.logger = logger;
		this.isupMatching = isupMatching;
		this.prMatching = prMatching;
	}

	@Override
	public void onData(IPCData data, String arg1, ChannelHandlerContext arg2,
			MessageEvent arg3) {		
		try {
			parceBody(new String(data.getBodyAsBytes()));
		} catch (Exception e) {
			logger.error("Parcing error: " + new String(data.getBodyAsBytes()), e);
		}
	}

	public void parceBody(String body) throws Exception{
		logger.info("Received body: " + body);
		if (body == null || body.isEmpty()) {
			logger.info("Body is null or empty.");
			return ;
		}
		StringTokenizer msgTok = new StringTokenizer(body, "|");
		
		String seq = getValue(msgTok.nextToken());
		String time = getValue(msgTok.nextToken());
		String gate = msgTok.nextToken();
		String link = msgTok.nextToken();
		String sio = msgTok.nextToken();
		String type = getValue(msgTok.nextToken());

		if (type.equals("IAM") || type.equals("REL")) {
			parceIAMREL(msgTok, seq, time, type);
		} else if (type.equals("P0") || type.equals("P1")) {
			parcePRN(msgTok, seq, time, type);
		} else if (type.equals("U0") || type.equals("I0")) {
			parceUI(msgTok, seq, time, type);
		} else {
			logger.error("Unknow message: type=" + type );
		}
	}
	
	private void parceIAMREL(StringTokenizer msgTok, String seq, String time, String type){
		String desPntCode = getValue(msgTok.nextToken());
		String orgPntCode = getValue(msgTok.nextToken());
		String cirIdnCode = getValue(msgTok.nextToken());
		String calling = null;
		String called = null;
		String errCode = null;
		
		if (type.equals("IAM")) {
			calling = getValue(msgTok.nextToken());
			called = getValue(msgTok.nextToken());
		} else errCode = getValue(msgTok.nextToken());
		
		ISUPMessage isupMsg = new ISUPMessage(
				Integer.parseInt(seq), 
				time, type, 
				desPntCode, 
				orgPntCode, 
				cirIdnCode, 
				calling, 
				called, 
				errCode
		);

		if (type.equals("IAM") && (calling == null || calling.isEmpty() || called == null || called.isEmpty())) {
			logger.info("REJECRED - calling or called null - " + isupMsg.toString());
			return ;		
		} else if (type.equals("REL") && (errCode == null || errCode.isEmpty())) {
			logger.info("REJECRED - errCode null - " + errCode.toString());
			return ;
		}
		
		isupMatching.put(isupMsg);
	}
	
	private void parcePRN(StringTokenizer msgTok, String seq, String time, String type){
		String orgTransId = getValue(msgTok.nextToken());
		String termTransId = getValue(msgTok.nextToken());
		String msgType = msgTok.nextToken();
		String orinSubsystem = msgTok.nextToken();
		String destSubsystem = msgTok.nextToken();
		String opc = msgTok.nextToken();
		String dpc = msgTok.nextToken();
		String callingGT = msgTok.nextToken();
		String calledGT = msgTok.nextToken();
		String msisdn = null;
		String imsi = null;
		String msc = null;
		String gmsc = null;
		String msrn = null;
		if (type.equals("P0")) {
			msisdn = getValue(msgTok.nextToken());
			imsi = getValue(msgTok.nextToken());
			msc = msgTok.nextToken();
			gmsc = msgTok.nextToken();
		} else {
			msrn = getValue(msgTok.nextToken());
		}
		
		PRMessage prMsg = new PRMessage(
				Integer.parseInt(seq), 
				time, type, 
				orgTransId, 
				termTransId, 
				imsi, 
				msisdn, 
				msrn
		);
		if (type.equals("P0") && (imsi == null || imsi.isEmpty())) {
			logger.info("REJECRED - imsi null - " + prMsg.toString());
			return ;		
		} else if (type.equals("P1") && (msrn == null || msrn.isEmpty())) {
			logger.info("REJECRED - msrn null - " + prMsg.toString());
			return ;
		}
		prMatching.put(prMsg);
	}

	private void parceUI(StringTokenizer msgTok, String seq, String time, String type) {
		String orgTransId = getValue(msgTok.nextToken());
		String termTransId = getValue(msgTok.nextToken());
		String msgType = msgTok.nextToken();
		String orinSubsystem = msgTok.nextToken();
		String destSubsystem = msgTok.nextToken();
		String opc = msgTok.nextToken();
		String dpc = msgTok.nextToken();
		String callingGT = getValue(msgTok.nextToken());
		String calledGT = getValue(msgTok.nextToken());
		String imsi = null;
		String msc = null;
		String vlr = null;
		String msisdn = null;
		if (type.equals("U0")) {
			imsi = getValue(msgTok.nextToken());
			msc = msgTok.nextToken();
			vlr = msgTok.nextToken();
		} else {
			msisdn = getValue(msgTok.nextToken());
		}
		
		UIMessage uiMsg = new UIMessage(
				Integer.parseInt(seq), 
				time, 
				type, 
				orgTransId, 
				termTransId, 
				calledGT, 
				callingGT, 
				imsi, 
				msisdn
		);

		if (type.equals("U0") && (imsi == null || imsi.isEmpty())) {
			logger.info("REJECRED - imsi null - " + uiMsg.toString());
			return ;
		} else if (type.equals("I0") && (msisdn == null || msisdn.isEmpty())) {
			logger.info("REJECRED - msisdn null - " + uiMsg.toString());
			return ;
		}
		
		uiMatching.put(uiMsg);
	}

	private String getValue(String key_value){
		String value = null;
		StringTokenizer strTok = new StringTokenizer(key_value, "=");
		strTok.nextToken();
		if (strTok.hasMoreTokens()) value = strTok.nextToken();
		return value;
	}
	
}
